﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Code.Models;
using Code.Commen;
using Code.BLL.Arithmetic;
using System.Data.SqlClient;
using Code.DAL;

namespace Code.BLL
{
    public class SchemeManage : ManageBase<Scheme>
    {
        /// <summary>
        /// 认购方案
        /// -1：系统错误，大于0 成功
        /// </summary>
        /// <exception cref="System.ArgumentNullException"/>
        /// <exception cref="Code.Models.ValidateException"/>
        /// <exception cref="Code.Models.AppException"/>
        public int Add(Scheme scheme, IEnumerable<Scheme_Detail> plays)
        {
            int rs = -1;
            if (scheme == null)
                throw new ArgumentNullException("scheme");
            if (plays == null || !plays.Any())
                throw new ArgumentNullException("plays");

            var issue = base.Select<Issue, Issue>(s => s.FirstOrDefault(p => p.ID == scheme.IssueID));
            var user = base.Select<Users, Users>(s => s.FirstOrDefault(p => p.ID == scheme.UserID));
            if (user == null)
                throw new ValidateException("用户不存在");

            if (issue == null)
                throw new ValidateException("期号不存在");
            else if (!(issue.StartTime < DateTime.Now && issue.EndTime > DateTime.Now.AddSeconds(issue.Lottery.ForwardEnd)))
                throw new ValidateException("该期以截止");

            var ratio = CacheManage.Ratio[scheme.ConsumptionRatio];
            if (ratio.State == (short)ConsumeRatioState.Locked)
                throw new ValidateException(ratio.Name + "模式已经停止使用！");
            var winmodel = CacheManage.WinModel[scheme.WinModelID];
            if (winmodel.State == (short)WinMoneyModelState.Locked)
                throw new ValidateException(winmodel.Name + "模式已经停止使用！");

            var playOptions = new PlayTypeOptionManage().GetUserOptionByRatio(scheme.UserID, scheme.LotteryID, scheme.WinModelID, scheme.ConsumptionRatio);
            var backToWinEnable = CacheManage.OptionSite[Option_Site_Key.Site_BackMoneyToWinMoney_Enable].ToBool(false);

            var fc = Arithmetic.LotteryFactory.CreateLottery((LotteryType)scheme.LotteryID);
            decimal singlebet = ratio.RadixMoney;
            scheme.SchemeMoney = scheme.SchemeCount = 0;
            List<AddDetailItem> details = new List<AddDetailItem>();
            int i = 0;

            foreach (var item in plays)
            {
                var playenum = (PlayType_E)item.PlayType.PlayTypeListID;

                var tp = fc.GetPlayType(playenum);
                //if (playenum == PlayType_E.XuanSanQianZhi)
                //{
                //    var num = tp.RegistNum(item.ChoseNumber);
                //    if (string.IsNullOrEmpty(num))
                //        throw new ValidateException(playenum.GetName() + "号码格式不正确：" + item.ChoseNumber);
                //}
                if (playenum == PlayType_E.RenXuanEr)
                   item.Count = tp.RenXuanEr(item.ChoseNumber);
                else if (playenum == PlayType_E.RenXuanSan)
                    item.Count = tp.RenXuanSan(item.ChoseNumber);
                else if (playenum == PlayType_E.RenXuanSi)
                    item.Count = tp.RenXuanSi(item.ChoseNumber);
                else if (playenum == PlayType_E.RenXuanWu)
                    item.Count = tp.RenXuanWu(item.ChoseNumber);
                else if (playenum == PlayType_E.RenErDanTuo)
                    item.Count = tp.RenErDanTuo(item.ChoseNumber);
                else if (playenum == PlayType_E.RenSanDanTuo)
                    item.Count = tp.RenSanDanTuo(item.ChoseNumber);
                else if (playenum == PlayType_E.RenSiDanTuo)
                    item.Count = tp.RenSiDanTuo(item.ChoseNumber);
                else if (playenum == PlayType_E.RenErDanTuo)
                    item.Count = tp.RenErDanTuo(item.ChoseNumber);
                else if (playenum == PlayType_E.RenWuDanTuo)
                    item.Count = tp.RenWuDanTuo(item.ChoseNumber);
                else if (playenum == PlayType_E.QianYiShuTou)
                    item.Count = tp.QianYiShuTou(item.ChoseNumber);
                else if (playenum == PlayType_E.QianYiHongTou)
                    item.Count = 1;
                else if (playenum == PlayType_E.XuanErLianZhi)
                    item.Count = tp.XuanErLianZhi(item.ChoseNumber);
                else if (playenum == PlayType_E.XuanSanQianZhi)
                    item.Count = tp.XuanSanQianZhi(item.ChoseNumber);
                else if (playenum == PlayType_E.XuanErLianZu)
                    item.Count = tp.RenXuanEr(item.ChoseNumber);
                else if (playenum == PlayType_E.XuanSanQianZu)
                    item.Count = tp.RenXuanSan(item.ChoseNumber);
                else if (playenum == PlayType_E.XuanErLianZuDanTuo)
                    item.Count = tp.XuanErLianZuDanTuo(item.ChoseNumber);
                else if (playenum == PlayType_E.XuanSanQianZuDanTuo)
                    item.Count = tp.XuanSanQianZuDanTuo(item.ChoseNumber);
                else if (playenum == PlayType_E.TCQianSanZhiXuan && scheme.LotteryID == 8)
                    item.Count = tp.TCQianSanZhiXuan(item.ChoseNumber);
                else if (playenum == PlayType_E.QianerZhiXuan && scheme.LotteryID == 8)
                    item.Count = tp.QianErZhiXuan(item.ChoseNumber);
                else
                    item.Count = tp.GetNumCount(item.ChoseNumber);

                item.Money = item.Count * singlebet * scheme.Multiple;
                scheme.SchemeCount += item.Count;
                scheme.SchemeMoney += item.Money;

                if (scheme.SchemeCount == 0 || scheme.SchemeMoney == 0)
                    throw new ValidateException("选择的号码不正确");

                var play = new AddDetailItem
                {
                    SchemeID = scheme.ID,
                    PlayTypeID = item.PlayTypeID,
                    IsCompound = item.IsCompound,
                    ChoseNumber = item.ChoseNumber,
                    Count = item.Count,
                    Money = item.Money,
                    BackMoneyToWinMoney = item.BackMoneyToWinMoney / 100,
                };
                details.Add(play);
                i++;
            }
            details.GroupBy(p => p.PlayTypeID).Each(pItem =>
            {
                var playType = CacheManage.PlayType[pItem.Key];
                var playTypeEnum = (PlayType_E)playType.PlayTypeListID;
                var playTypeProduct = fc.GetPlayType(playTypeEnum);

                if (playType.MaxBuyCount.HasValue && pItem.Sum(p1 => p1.Count) > playType.MaxBuyCount)
                    throw new ValidateException(string.Format("\"{0}\" 最多只能购买 {1} 注", playType.PlayTypeList.Name, playType.MaxBuyCount));
                if (playType.MaxBuyMultiple.HasValue && scheme.Multiple > playType.MaxBuyMultiple)
                    throw new ValidateException(string.Format("\"{0}\"最多只能购买 {1} 倍", playType.PlayTypeList.Name, playType.MaxBuyMultiple));

                int num;
                var maxnumber = playType.MaxBuyNumber.Split(',').Select(p1 => int.TryParse(p1, out num) ? num : -1).ToArray();

                List<string>[] nums = maxnumber.Select(p1 => new List<string>()).ToArray();
                if (scheme.Lottery==null)
                {
                    pItem.Each(item =>
                        {
                            playTypeProduct.GetChoseNumberList(item.ChoseNumber).Each(pp =>
                                pp.Split(',').Each((p2, j) =>
                                    {
                                        var t = p2.Select(p3 => p3.ToString());
                                        if (t.Contains(",") || t.Contains(" "))
                                            t = p2.Split(new char[] {',', ' '});
                                        t.Each(p3 => { if (!nums[j].Contains(p3)) nums[j].Add(p3); });
                                    }));
                        });
                }

                nums.Each((p1, j) =>
                {
                    if (maxnumber[j] >= 0 && p1.Count > maxnumber[j])
                        throw new ValidateException(string.Format("\"{0}\"第 {1} 位最多只能买 {2} 个号码", playTypeEnum.GetName(), j + 1, maxnumber[j]));
                });

                if (!string.IsNullOrEmpty(playType.RestrictiveNumber))
                {
                    var res = new List<string>();
                    var r = playType.RestrictiveNumber.Split('|');
                    var b = new List<string>();
                    pItem.Each(p1 => b.AddRange(playTypeProduct.GetChoseNumberList(p1.ChoseNumber)));
                    r.Each(p1 => res.AddRange(playTypeProduct.GetChoseNumberList(p1).Where(p2 => b.Contains(p2))));
                    if (res.Count > 0)
                        throw new BetValidateException(string.Format("\"{0}\" 不能投注：{1}", playTypeEnum.GetName(), string.Join("、", res.Distinct().ToArray())));
                }
                
                var playOpt = playOptions.First(pp => pp.PlayTypeID == pItem.Key);
                pItem.Each(item =>
                    {
                        if(backToWinEnable && item.BackMoneyToWinMoney.HasValue)
                        {
                            if (item.BackMoneyToWinMoney < 0)
                                throw new BetValidateException("参数不正确");
                            else if (item.BackMoneyToWinMoney.Value * 100 > (decimal)playOpt.MaxBackMoneyToWinMoney)
                                throw new BetValidateException(string.Format("\"{0}\" 返点加奖最多：{1}%", playTypeEnum.GetName(), playOpt.MaxBackMoneyToWinMoney));
                        }
                        else if (item.BackMoneyToWinMoney.HasValue)
                        {
                            throw new BetValidateException("不能使用返点加奖功能");
                        }
                    });
            });


            var scheme2 = new
            {
                scheme.ID,
                scheme.IssueID,
                scheme.Multiple,
                scheme.Share,
                scheme.ConsumptionRatio,
                scheme.SchemeMoney,
                scheme.SchemeCount,
                scheme.UserID,
                scheme.WinModelID,
                scheme.LotteryID
            };

            if (user.Account.Balance < scheme2.SchemeMoney)
                throw new ValidateException("余额不足");

            base.BeginTransaction();
            base.Insert(scheme2);
            base.Update<Account>(new { Balance = new OpteratorValue(Opterator.Subtract, scheme2.SchemeMoney) }, new { UserID = user.ID });
            base.Insert<Scheme_Detail>(details.ToArray());
            i += 2;

            rs = base.ExecuteTransaction(i);
        
            return rs;
        }


        /// <summary>
        /// 出票
        /// </summary>
        /// <param name="issue">要出票的期号</param>
        /// <exception cref="Code.Models.AppException"/>
        /// <exception cref="Code.Models.ValidateException"/>
        public void OutBill(long issueid, IEnumerable<Scheme> schemes = null)
        {
            var issue = base.Select<Issue, Issue>(s => s.FirstOrDefault(p => p.ID == issueid));
            if (issue == null)
                throw new AppException("期号不正确");
            if (issue.EndTime > DateTime.Now)
                throw new AppException("该期未截止");

            var PM = new PlayTypeOptionManage();
            Scheme[] schem;
            if (schemes == null)
                schem = base.Select(s => s.Where(p => p.IssueID == issue.ID && p.State == (short)SchemeState.Normal)).ToArray();
            else
                schem = schemes.ToArray();
            int schemesCount = schem.Length;
            int error = 0;

            foreach (var scheme in schem)
            {
                int rs = OutBill(scheme);
                if (rs < 0)
                    error++;
            }
            if (schemesCount > 0 && Log.IsInfoEnabled)
                Log.InfoFormat("{4} 第{3}期出票：方案 {0} 个，成功 {1} 个、失败 {2} 个！", schemesCount, schemesCount - error, error, issue.FormatIssueName, ((LotteryType)issue.LotteryID).GetName());
        }

        /// <summary>
        /// 出票+升级
        /// </summary>
        public int OutBill(Scheme scheme)
        {
            int rs= base.Update(new { State = (short)SchemeState.OutBill }, new { scheme.ID, State = (short)SchemeState.Normal });
            if(rs>0)
            {
                UpRank UpRank = base.Select<UpRank, UpRank>(s => s.FirstOrDefault(p => p.UsersId == scheme.UserID));
                int thisExpert = UpRank.ThisExpert;
                var option = Code.BLL.CacheManage.OptionSite[Code.Models.Option_Site_Key.Site_Cache_ChangeExp];
                int Site_Cache_ChangeExp = Convert.ToInt32(option.Value);
                thisExpert += (int)(scheme.SchemeMoney / Site_Cache_ChangeExp);
                Rank Rank = base.Select<Rank, Rank>(s => s.OrderByDescending(j => j.Exper).FirstOrDefault(p => p.Exper <= thisExpert));
                Rank model = base.Select<Rank, Rank>(s => s.OrderBy(p => p.Exper).FirstOrDefault(j => j.Id > 0));
                int res = 0;
                using (SqlConnection conn = new SqlConnection(DBHelper.Connection.ConnectionString))
                {
                    conn.Open();
                    string sql = "update UpRank set ThisExpert=@thisExpert,RankId=@rankId where UsersId=@uid";
                    SqlCommand com = new SqlCommand(sql, conn);
                    com.Parameters.AddWithValue("@thisExpert", thisExpert);
                    if (Rank == null)
                    {
                        com.Parameters.AddWithValue("@rankId", model.Id);
                    }
                    else
                    {
                        com.Parameters.AddWithValue("@rankId", Rank.Id);
                    }
                    com.Parameters.AddWithValue("@uid", scheme.UserID);
                    res = com.ExecuteNonQuery();
                }
                var us = base.Select<Users, Users>(s => s.FirstOrDefault(p => p.ID == scheme.UserID));
                base.BeginTransaction();
                if (Rank.Id != UpRank.RankId)
                {
                    base.Update<Account>(new { Balance = new OpteratorValue(Opterator.Add, Rank.ResetMoneyToMy) }, new { UserID = scheme.UserID });
                    base.Insert<OtherMoneyDetail>(new { scheme.UserID, Type = (short)OtherMoneyDetailType.UpRankAddSelf, Money = Rank.ResetMoneyToMy, Memo = string.Format("升{0}级奖励奖金", Rank.Ranks) });
                    if (us.CommandID != null)
                    {
                        base.Update<Account>(new { Balance = new OpteratorValue(Opterator.Add, Rank.ResetMoneyToUp) }, new { UserID = us.CommandID });
                        base.Insert<OtherMoneyDetail>(new { UserID = us.CommandID, Type = (short)OtherMoneyDetailType.UpRankAddCommand, Money = Rank.ResetMoneyToUp, Memo = string.Format("下级升{0}级奖励奖金", Rank.Ranks) });
                    }
                }

                int num = base.ExecuteTransaction();
            }
            
            return rs;
        }

        /// <summary>
        /// 开奖,如果为追号任务执行追号
        /// </summary>
        /// <param name="issueid">要开奖的期号</param>
        /// <exception cref="Code.Models.AppException"/>
        /// <exception cref="Code.Models.ValidateException"/>
        public void OpenWin(long issueid)
        {
            var issue = base.Select<Issue, Issue>(s => s.FirstOrDefault(p => p.ID == issueid && p.EndTime <= DateTime.Now));
            if (issue == null)
                throw new AppException("期号不正确");
            if (issue.State != (short)IssueState.Opened)
                throw new ValidateException("该期未开奖");


            var schemes = base.Select(s => s.Where(p => p.IssueID == issue.ID && p.State == (short)SchemeState.OutBill).ToArray());
            int schemesCount = schemes.Length;
            int error = 0;
            int wincount = 0;
            int rs;

            foreach (var scheme in schemes)
            {
                try
                {
                    rs = SchemeOpenWin(scheme, issue);
                }
                catch { rs = -1; }
                if (rs < 0)
                    error++;
                else if (rs > 0)
                    wincount++;
            }
            if (schemesCount > 0 && Log.IsInfoEnabled)
                Log.InfoFormat("{0} 第{1}派奖：方案{2}个,中奖{3}个，成功{4}个、失败{5}个！",
                    ((LotteryType)issue.LotteryID).GetName(), issue.FormatIssueName, schemesCount, wincount, schemesCount - error, error);

            //追号 方案开奖后才能决定是否追下期
            ChaseManage CM = new ChaseManage();
            CM.Exec((LotteryType)issue.LotteryID);
        }

        /// <summary>
        /// 给指定的方案开奖 大于0为中奖,等于0为未中奖，小于0为开奖出错
        /// </summary>
        /// <param name="scheme">要开奖的方案</param>
        /// <param name="issue">该期的信息</param>
        public int SchemeOpenWin(Scheme scheme, Issue issue = null)
        {
            return SchemeBackMoneyAndOpenWin(scheme, issue);

        }

        /// <summary>
        /// 计算返点和派奖
        /// </summary>
        /// <param name="scheme"></param>
        /// <param name="issue"></param>
        /// <returns></returns>
        private int SchemeBackMoneyAndOpenWin(Scheme scheme, Issue issue = null)
        {
            int rs = -1;
            try
            {
                if (scheme.Share != 1 && (Log.IsErrorEnabled || Log.IsInfoEnabled || Log.IsDebugEnabled))
                    Log.ErrorFormat("派奖：未实现合买功能 方案 {0} 标记为合买，份数:{1}！", scheme.ID, scheme.Share);

                var PM = new PlayTypeOptionManage();
                if (issue == null)
                    issue = new IssueManage().Select(s => s.FirstOrDefault(p => p.ID == scheme.IssueID && p.EndTime <= DateTime.Now));
                if (issue == null)
                    throw new AppException("期号不正确");
                if (issue.State != (short)IssueState.Opened)
                    throw new ValidateException("该期未开奖");
                if (scheme.State != (short)SchemeState.OutBill)
                    throw new ValidateException("方案已为" + ((SchemeState)scheme.State).GetName());

                var factory = Code.BLL.Arithmetic.LotteryFactory.CreateLottery((LotteryType)issue.LotteryID);

                var winDetails = scheme.Scheme_Detail.Select(p => new
                {
                    p.ID,
                    p.PlayTypeID,
                    p.Money,
                    Item = p,
                    WinNumber = factory.GetPlayType((PlayType_E)CacheManage.PlayType[p.PlayTypeID].PlayTypeListID).GetWinNums(p.ChoseNumber, issue.OpenCode).ToArray()
                }).ToArray();
                
                int upcount = -1;
                bool isWin = false;
                decimal selfwinmoney = -1;

                isWin = winDetails.Any(p => p.WinNumber.Length > 0); //是否中奖

                #region 计算用户返点和奖金

                var u = base.Select<Users, Users>(s => s.FirstOrDefault(p => p.ID == scheme.UserID));
                if (u == null)
                    throw new ValidateException("出票:方案" + scheme.ID + "用户不存在");
                var tp = u.Commands.Split("&".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Select(p => new Guid(p));
                var commanders = base.Select<Users, IEnumerable<Users>>(s => s.Where(p => tp.Contains(p.ID))).Select(p => new { p.ID, p.CommandID }).ToList();
                commanders.Insert(0, new { u.ID, u.CommandID });

                var groupDetails = winDetails.GroupBy(p => p.PlayTypeID, p => p);
                var userwins = PM.GetSelfAndCommanderOptions(scheme.UserID, issue.LotteryID, scheme.WinModelID, true)
                    .ToDictionary(p => p.Key, p => p.Value.ToDictionary(pp => pp.PlayTypeID, pp => pp));
                var sitewin = PM.GetWinMoneyOption(null, issue.LotteryID, scheme.WinModelID, true)
                    .ToDictionary(p => p.PlayTypeID, p => p);
                var useSiteBack = CacheManage.OptionSite[Option_Site_Key.Site_Lottery_UseSiteBackMoneyRatio].ToBool(false);
                var useSiteWin = CacheManage.OptionSite[Option_Site_Key.Site_Lottery_UseSiteWinMoney].ToBool(false);
                var ratio = CacheManage.Ratio[scheme.ConsumptionRatio];

                var allUserBackWinMoney = commanders.ToDictionary(p => p.ID, p => 0m);//返奖
                var allUserBackMoney = commanders.ToDictionary(p => p.ID, p => 0m);//返点

                foreach (var groupDetail in groupDetails)
                {
                    var winlen = groupDetail.Sum(p => p.WinNumber.Length);
                    foreach (var user in commanders)
                    {
                        if (user.CommandID.HasValue)
                        {
                            var selfOption = userwins[user.ID][groupDetail.Key];
                            var commanderOption = (user.CommandID.HasValue ? userwins[user.CommandID.Value] : sitewin)[groupDetail.Key];
                            
                            //给上级用户返奖
                            if (!useSiteWin && isWin && winlen > 0) 
                            {
                                if (commanderOption.WinMoney < selfOption.WinMoney)
                                {
                                    if (Log.IsErrorEnabled)
                                        Log.ErrorFormat("派奖:方案 {0} 出错 奖金设置下级{3}:{1}高于上级{4}:{2}", scheme.ID, selfOption.WinMoney, commanderOption.WinMoney, user.ID, user.CommandID);
                                    return -1;
                                }
                                allUserBackWinMoney[user.CommandID.Value] += Math.Round(groupDetail.Sum(pp => pp.WinNumber.Length) * (decimal)(commanderOption.WinMoney - selfOption.WinMoney) * scheme.Multiple * scheme.ConsumptionRatio, 4);
                            }

                            //给上级返点
                            if (!useSiteBack)
                            {
                                if (commanderOption.BackMoneyRatio < selfOption.BackMoneyRatio)
                                {
                                    if (Log.IsErrorEnabled)
                                        Log.ErrorFormat("出票:方案 {0} 出错 返点设置下级{3}:{1}高于上级{4}:{2}", scheme.ID, selfOption.BackMoneyRatio, commanderOption.BackMoneyRatio, user.ID, user.CommandID);
                                    return -1;
                                }
                                if (selfOption.BackMoneyRatio < 0 || commanderOption.BackMoneyRatio < 0)
                                {
                                    if (Log.IsErrorEnabled)
                                        Log.ErrorFormat("出票:方案 {0} 出错 返点设置出错{3}:会员返点{1}可能存在作弊行为{4}:代理返点{2}", scheme.ID, selfOption.BackMoneyRatio, commanderOption.BackMoneyRatio, user.ID, user.CommandID);
                                    return -1;

                                }
                                var temp = ((decimal)commanderOption.BackMoneyRatio - ratio.BackMoneyDifference) - ((decimal)selfOption.BackMoneyRatio - ratio.BackMoneyDifference);
                                if (temp < 0)
                                    temp = 0;
                                allUserBackMoney[user.CommandID.Value] += Math.Round(groupDetail.Sum(p => p.Money) * temp, 4);
                            }
                        }
                    }

                    var winOpt = useSiteBack ? sitewin[groupDetail.Key] : userwins[scheme.UserID][groupDetail.Key];
                    var num = (decimal) winOpt.BackMoneyRatio - ratio.BackMoneyDifference;
                    if (num < 0)
                        num = 0;

                    //原用户返点计算方式
                    //backmoney[scheme.UserID] += Math.Round(detail.Sum(p => p.Money) * num, 4);   //用户返点

                    //返点加奖用户返点计算方式
                    groupDetail.Each(p =>
                        {
                            if(p.Item.BackMoneyToWinMoney.HasValue && p.Item.BackMoneyToWinMoney > 0)
                            {
                                //如果用户当前返点比下注时返点小，则用当前返点。
                                var backToWin = Math.Min(num, p.Item.BackMoneyToWinMoney.Value);
                                num -= backToWin;

                                if (backToWin > 0)
                                {
                                    //加奖给用户
                                    var addMoney = backToWin * 100 * (decimal)winOpt.BackMoneyToWinMoneyRatio;
                                    p.Item.BackMoneyToWinMoneyToWin = Math.Round(p.WinNumber.Length * addMoney * scheme.Multiple * scheme.ConsumptionRatio , 4);
                                    allUserBackWinMoney[scheme.UserID] += p.Item.BackMoneyToWinMoneyToWin.Value;
                                }
                            }
                            
                            if(num > 0)
                                allUserBackMoney[scheme.UserID] += Math.Round(p.Money * num, 4);
                        });
                    
                    //用户奖金
                    if (isWin && winlen > 0)
                    {   
                        if (useSiteWin)
                            allUserBackWinMoney[scheme.UserID] += Math.Round(groupDetail.Sum(pp => pp.WinNumber.Length) * (decimal)sitewin[groupDetail.Key].WinMoney * scheme.Multiple * scheme.ConsumptionRatio, 4);
                        else
                            allUserBackWinMoney[scheme.UserID] += Math.Round(groupDetail.Sum(pp => pp.WinNumber.Length) * (decimal)userwins[scheme.UserID][groupDetail.Key].WinMoney * scheme.Multiple * scheme.ConsumptionRatio, 4);
                    }
                }


                //更新到数据库
                var backmoneyAccount = allUserBackMoney.ToNameValue(p => (object)(p.Key == scheme.UserID ?
                    new NameValue<string, object> { { "Balance", new OpteratorValue(Opterator.Add, p.Value) }, { "BackMoney", new OpteratorValue(Opterator.Add, p.Value) }, { "BuyLottery", new OpteratorValue(Opterator.Add, scheme.SchemeMoney) } } :
                    new NameValue<string, object> { { "Balance", new OpteratorValue(Opterator.Add, p.Value) }, { "BackMoney_Child", new OpteratorValue(Opterator.Add, p.Value) } })
                    , p => (object)new { UserID = p.Key });

                NameValue<string, object>[] backmoneyDetail;
                if (useSiteBack)
                    backmoneyDetail = new NameValue<string, object>[] { new NameValue<string, object> { { "UserID", scheme.UserID }, { "BackUserID", scheme.UserID }, { "SchemeID", scheme.ID }, { "Money", allUserBackMoney[scheme.UserID] } } };
                else
                    backmoneyDetail = allUserBackMoney.Select(p => new NameValue<string, object> { { "UserID", p.Key }, { "BackUserID", scheme.UserID }, { "SchemeID", scheme.ID }, { "Money", p.Value } }).ToArray();

                base.BeginTransaction();
                base.Update<Account>(backmoneyAccount);//加返点
                base.Insert<BackMoneyDetail>(backmoneyDetail);//加返点记录
                upcount = backmoneyAccount.Count + backmoneyDetail.Length;

                if (isWin)
                {
                    decimal sumWimMoney = 0;
                    var winmoneyAccount = allUserBackWinMoney.ToNameValue(p => (object)(p.Key == scheme.UserID ?
                        new NameValue<string, object> { { "Balance", new OpteratorValue(Opterator.Add, p.Value) }, { "WinMoney", new OpteratorValue(Opterator.Add, p.Value) } } :
                        new NameValue<string, object> { { "Balance", new OpteratorValue(Opterator.Add, p.Value) }, { "WinMoney_Child", new OpteratorValue(Opterator.Add, p.Value) } })
                        , p => (object)new { UserID = p.Key });
                    var schemeDetail = winDetails.ToNameValue(p =>
                    {
                        //计算玩法奖金 + 返点加奖
                        var winmoney = p.WinNumber.Length * (decimal)sitewin[p.PlayTypeID].WinMoney * scheme.Multiple * scheme.ConsumptionRatio;
                        p.Item.OriginalWinMoney = winmoney;
                        
                        if (p.Item.BackMoneyToWinMoneyToWin.HasValue)
                            winmoney += p.Item.BackMoneyToWinMoneyToWin.Value;
                        sumWimMoney += winmoney;
                        
                        var up = new NameValue<string, object>
                            {
                                {"WinNumber", p.WinNumber.Length == 0 ? string.Empty : string.Join("&", p.WinNumber)},
                                {"WinMoney", winmoney},
                                {"BackMoneyToWinMoneyToWin", p.Item.BackMoneyToWinMoneyToWin},
                                {"OriginalWinMoney", p.Item.OriginalWinMoney},
                            };
                        return (object)up;
                    }, p => (object)new NameValue<string, object> { { "ID", p.ID } });

                    decimal sumUserWinMoney = allUserBackWinMoney.Sum(p => p.Value);

                    if (sumUserWinMoney > sumWimMoney)
                    {
                        if (Log.IsErrorEnabled)
                            Log.ErrorFormat("派奖：奖金金额不正确,方案奖金:{0} 支出奖金:{1}", sumWimMoney, sumUserWinMoney);
                    }
                    object[] backWinMoneyDetail;
                    if (useSiteWin)
                        backWinMoneyDetail = new object[] { new NameValue<string, object> { { "UserID", scheme.UserID }, { "WinUserID", scheme.UserID }, { "SchemeID", scheme.ID }, { "Money", allUserBackWinMoney[scheme.UserID] } } };
                    else
                        backWinMoneyDetail = allUserBackWinMoney.Select(p => new NameValue<string, object> { { "UserID", p.Key }, { "WinUserID", scheme.UserID }, { "SchemeID", scheme.ID }, { "Money", p.Value } }).ToArray();

                    base.Update(new { State = (short)SchemeState.Opened, WinMoney = sumWimMoney }, new { scheme.ID, State = (short)SchemeState.OutBill });
                    base.Update<Scheme_Detail>(schemeDetail);
                    base.Update<Account>(winmoneyAccount);
                    base.Insert<WinMoneyDetail>(backWinMoneyDetail);
                    upcount += 1 + schemeDetail.Count + winmoneyAccount.Count + backWinMoneyDetail.Length;

                    selfwinmoney = allUserBackWinMoney[scheme.UserID];
                }
                else
                {
                    base.Update(new { State = (short)SchemeState.Opened }, new { scheme.ID, State = (short)SchemeState.OutBill });
                    upcount += 1;
                }
                #endregion


                rs = base.ExecuteTransaction(upcount);
                if (rs < 0)
                {
                    if (Log.IsErrorEnabled)
                        Log.ErrorFormat("派奖：方案 {0} 派奖失败！", scheme.ID);
                }
                else
                {
                    rs = selfwinmoney < 0 ? 0 : 1;

                    #region 追号
                    if (scheme.IsChaseTask) //如果为追号任务
                    {
                        try
                        {

                            var task = base.Select<ChaseTask_Detail, ChaseTask>(s => s.Where(p => p.SchemeID == scheme.ID).Select(p => p.ChaseTask).FirstOrDefault());
                            if (task == null)
                            {
                                if (Log.IsErrorEnabled)
                                    Log.ErrorFormat("派奖：方案{0}为追号方案,获取时追号明细失败！", scheme.ID);
                            }
                            else
                            {
                                var taskdetail = base.Select<ChaseTask_Detail, ChaseTask_Detail>(s => s.FirstOrDefault(p => p.ChaseTaskID == task.ID && p.Issue.StartTime <= DateTime.Now && p.Issue.EndTime > DateTime.Now));
                                if (taskdetail != null && taskdetail.State == (short)ChaseTaskState.Normal)
                                {
                                    ChaseManage CM = new ChaseManage();
                                    if (task.StopWin < 0 || selfwinmoney < task.StopWin)
                                        CM.ExecChaseTask(task.ID);
                                    else
                                        CM.CancelTask(task.ID, ChaseTaskState.WinCancel);
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            string errormsg;
                            if (e is AppException)
                                errormsg = "追号:" + e.Message;
                            else
                                errormsg = "追号:系统错误";

                            if (Log.IsDebugEnabled)
                                Log.Error(errormsg, e);
                            else if (Log.IsErrorEnabled)
                                Log.Error(errormsg);
                        }
                    }
                    #endregion
                }
            }
            catch (Exception e)
            {
                if (Log.IsDebugEnabled)
                    Log.Debug("派奖:方案" + scheme.ID + " 派奖出错", e);
                else if (Log.IsErrorEnabled)
                    Log.ErrorFormat("派奖:方案{0} 派奖出错:{1}", scheme.ID, e.Message);
                else if (Log.IsInfoEnabled)
                    Log.InfoFormat("派奖:方案{0} 派奖出错", scheme.ID);
                if (!(e is AppException))
                    throw e;
            }
            return rs;
        }

        /// <summary>
        /// 补奖 大于0为中奖,等于0为未中奖，小于0为开奖出错
        /// </summary>
        public int BuJian(Guid schemeid)
        {
            int rs = -1;
            //不能补奖的状态
            var states = new short[] { (short)SchemeState.Opened, (short)SchemeState.SysCancel, (short)SchemeState.UserCancel };
            var scheme = base.Select(s => s.FirstOrDefault(p => p.ID == schemeid));
            if (scheme == null)
            {
                throw new ArgumentNullException("不存在该方案");
            }
            if (states.Contains(scheme.State))
            {
                throw new ValidateException("方案" + ((SchemeState)scheme.State).GetName() + "无法补奖");
            }
            if (scheme.State == (short)SchemeState.Normal)  //未出票
            {
                rs = OutBill(scheme);
                if (rs > 0)
                    scheme.State = (short)SchemeState.OutBill;
                else
                    throw new AppException("出票失败！");
            }

            if (scheme.State == (short)SchemeState.TimeOutCancel)    //被撤消
            {
                var acc = base.Select<Account, Account>(s => s.FirstOrDefault(p => p.UserID == scheme.UserID));
                if (acc.Balance < scheme.SchemeMoney)
                    throw new ValidateException("账户余额不足，操作失败！");

                base.BeginTransaction();
                base.Update(new { State = SchemeState.OutBill }, new { scheme.ID, scheme.State });
                base.Insert<OtherMoneyDetail>(new { scheme.UserID, Type = (short)OtherMoneyDetailType.BackTimeOutScheme, Money = scheme.SchemeMoney, Memo = "补奖", Remark = string.Format("RefID:{0}", scheme.ID) });
                base.Update<Account>(new { Balance = new OpteratorValue(Opterator.Subtract, scheme.SchemeMoney) }, new { scheme.UserID });
                int trs = base.ExecuteTransaction(3);

                if (trs < 0 && Log.IsDebugEnabled)
                    Log.DebugFormat("方案:回滚补奖方案{0}金额:{1}失败！", scheme.ID, scheme.SchemeMoney.ToString("C"));
                else if (trs < 0 && Log.IsErrorEnabled)
                    Log.ErrorFormat("方案:回滚补奖方案{0}金额:{1}失败！", scheme.ID, scheme.SchemeMoney.ToString("C"));
                else if (trs < 0 && Log.IsInfoEnabled)
                    Log.InfoFormat("方案:回滚补奖方案{0}金额:{1}失败！", scheme.ID, scheme.SchemeMoney.ToString("C"));

                if (trs > 0)
                    scheme.State = (short)SchemeState.OutBill;
                else
                    throw new AppException("系统错误，操作失败！");

            }

            //开奖
            try { rs = SchemeOpenWin(scheme); }
            catch (Exception e)
            {
                if (Log.IsDebugEnabled)
                    Log.Debug(string.Format("方案:方案{0}补奖失败！", scheme.ID), e);
                else if (Log.IsErrorEnabled)
                    Log.ErrorFormat("方案:方案{0}补奖失败！", scheme.ID, e.Message);
                else if (Log.IsInfoEnabled)
                    Log.InfoFormat("方案:方案{0}补奖失败！", scheme.ID);
                throw e;
            }

            return rs;
        }


        /// <summary>
        /// 撤消过期未开奖的方案 默认为撤消所有未开奖的方案
        /// </summary>
        public void CancleTimeOutSchemes(long issueid = -1)
        {
            IEnumerable<Guid> schemes;
            if (issueid < 0)
                schemes = base.Select(s => s.Where(p => p.State == (short)SchemeState.Normal &&
                    p.Issue.EndTime < DateTime.Now && p.Issue.State == (short)IssueState.Normal).Select(p => p.ID));
            else
                schemes = base.Select(s => s.Where(p => (p.State == (short)SchemeState.Normal || p.State == (short)SchemeState.OutBill) && p.IssueID == issueid &&
                p.Issue.EndTime < DateTime.Now && p.Issue.State == (short)IssueState.Normal).Select(p => p.ID));

            schemes.Each(p =>
            {
                try { CancleScheme(p, SchemeState.TimeOutCancel); }
                catch (Exception e)
                {
                    if (Log.IsDebugEnabled) Log.Debug("方案:撤销方案" + p + "失败,原因:" + e.Message, e);
                    else if (Log.IsErrorEnabled)
                        Log.ErrorFormat("方案:撤销方案{0}失败:{1}", p, e.Message);
                    else if (Log.IsInfoEnabled)
                        Log.InfoFormat("方案:撤销方案{0}失败:{1}", p, e.Message);
                }
            });
        }

        /// <summary>
        /// 撤消方案
        /// </summary>
        /// <param name="id">要撤消的方案</param>
        /// <param name="state">撤消的状态</param>
        /// <param name="uid">要撤消的方案所属的用户的ID,用于验证当前方案是否属于指定用户。(默认为不验证)</param>
        /// <exception cref="System.ArgumentOutOfRangeException"/>
        /// <exception cref="Code.Models.AppException"/>
        /// <exception cref="Code.Models.ValidateException"/>
        public int CancleScheme(Guid id, SchemeState state, Guid? uid = null)
        {
            var cs = new SchemeState[] { SchemeState.SysCancel, SchemeState.TimeOutCancel, SchemeState.UserCancel };

            var scheme = base.Select(s => s.FirstOrDefault(p => p.ID == id));
            if (scheme == null)
                throw new ValidateException("方案不存在");
            if (state == SchemeState.UserCancel)
            {
                var ck = base.Select<Issue, Issue>(s => s.First(p => p.ID == scheme.IssueID));
                if (ck.EndTime < DateTime.Now.AddSeconds(CacheManage.Lottery[(LotteryType)scheme.LotteryID].ForwardEnd))
                    throw new ValidateException("认购已截止");
            }
            if (uid.HasValue && scheme.UserID != uid.Value)
                throw new ValidateException("方案不属于该用户");
            if (!cs.Contains(state))
                throw new ArgumentOutOfRangeException("state", "不支持的撤销状态");
            //if (scheme.State == (short)SchemeState.OutBill)   //出票不算返点，则可撤销方案
            //    throw new ValidateException("方案已出票");
            if (scheme.State == (short)SchemeState.Opened)
                throw new ValidateException("方案已开奖");
            if (cs.Contains((SchemeState)scheme.State))
                throw new ValidateException("方案已为" + ((SchemeState)scheme.State).GetName());
            //if (scheme.State != (short)SchemeState.Normal)
            //    throw new ValidateException("未知的方案状态");
            if (scheme.Share > 1)
                throw new ValidateException("合买方案，不能撤消");

            base.BeginTransaction();
            base.Insert<OtherMoneyDetail>(new { scheme.UserID, Type = (short)OtherMoneyDetailType.SchemeCancle, Money = scheme.SchemeMoney, Memo = state.GetName(), Remark = string.Format("RefID:{0}", scheme.ID) });
            base.Update(new { State = (short)state }, new { scheme.ID, scheme.State });
            base.Update<Account>(new { Balance = new OpteratorValue(Opterator.Add, scheme.SchemeMoney) }, new { scheme.UserID });
            int rs = base.ExecuteTransaction(3);
            if (rs < 0 && Log.IsDebugEnabled)
                Log.DebugFormat("方案:撤销方案{0}失败！", scheme.ID);
            else if (rs < 0 && Log.IsErrorEnabled)
                Log.ErrorFormat("方案:撤销方案{0}失败！", scheme.ID);
            else if (rs < 0 && Log.IsInfoEnabled)
                Log.InfoFormat("方案:撤销方案{0}失败！", scheme.ID);
           
            return rs;
        }

        /// <summary>
        /// 更新Scheme表数据
        /// </summary>
        /// <param name="update">要更新的属性,类的属性名要和表的列名一致</param>
        /// <param name="where">做为筛选的条件,类的属性名要和表的列名一致 无条件则为 null</param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>更新的行数</returns>
        public int UpdateScheme(object update, object where)
        {
            return base.Update(update, where);
        }

        /// <summary>
        /// 更新Scheme_Detail表数据
        /// </summary>
        /// <param name="update">要更新的属性,类的属性名要和表的列名一致</param>
        /// <param name="where">做为筛选的条件,类的属性名要和表的列名一致 无条件则为 null</param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>更新的行数</returns>
        public int UpdateScheme_Detail(object update, object where)
        {
            return base.Update<Scheme_Detail>(update, where);
        }

        #region 方案管理
        /// <summary>
        /// 获取方案详情
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="where"></param>
        /// <param name="paramList"></param>
        /// <returns></returns>
        public IEnumerable<Scheme_Mod> SchemeList(Guid uid, int skip, int take, out int sumCount, string where = null, object[] paramList = null)
        {
            var data = base.Select(s => s.Where(p => p.UserID == uid).Where(where ?? " 1==1 ", paramList ?? new object[0]));
            sumCount = data.Count();
            var newData = data.OrderByDescending(p => p.AddTime).Skip(skip).Take(take).Select(p => new
            {
                p.ID,
                p.Issue.Number,
                p.SchemeCount,
                p.SchemeMoney,
                p.Multiple,
                p.Issue.OpenCode,
                p.Share,
                p.State,
                p.AddTime,
                p.IsChaseTask,
                p.LotteryID,
                p.WinModelID,
                p.ConsumptionRatio,
                p.WinMoney,
                p.Issue.EndTime,
                UserWinMoney = (double?)p.WinMoneyDetail.Where(p1 => p1.UserID == p.UserID).Select(p1 => p1.Money).FirstOrDefault()
            }).ToArray();
            var schemeList = newData.Select(p => new Scheme_Mod
            {
                SchemeID = p.ID,
                IssueNumber = new Issue { Number = p.Number, LotteryID = p.LotteryID }.FormatIssueName,
                SchemeCount = p.SchemeCount,
                SchemeMoney = (double)p.SchemeMoney,
                SchemeMultiple = p.Multiple,
                SchemeOpenCode = p.OpenCode,
                SchemeShare = p.Share,
                SchemeState = p.State,
                AddTime = p.AddTime,
                IsChaseTask = p.IsChaseTask,
                LotteryName = CacheManage.Lottery.Where(p1 => p1.Value.ID == p.LotteryID).Select(p1 => p1.Value.Name).FirstOrDefault(),
                WinModelName = CacheManage.WinModel.Where(p1 => p1.Value.ID == p.WinModelID).Select(p1 => p1.Value.Name).FirstOrDefault(),
                ConsumptionRatioName = CacheManage.Ratio.Where(p1 => p1.Value.Ratio == p.ConsumptionRatio).Select(p1 => p1.Value.Name).FirstOrDefault(),
                SchemeWinMoney = (double?)p.WinMoney,
                UserWinMoney = p.UserWinMoney,
                IsEnd = p.EndTime < DateTime.Now.AddSeconds(CacheManage.Lottery[(LotteryType)p.LotteryID].ForwardEnd)

            });

            return schemeList;
        }

        /// <summary>
        /// 获取方案明细详情
        /// </summary>
        public IEnumerable<SchemeDetail_Mod> SchemeDetailList(Guid schemeID, Guid uid, int skip, int take, out int sumCount)
        {
            var data = base.Select<Scheme_Detail, IEnumerable<Scheme_Detail>>(s => s.Where(p => p.SchemeID == schemeID && (p.Scheme.Users.Commands.Contains(uid.ToString()) || p.Scheme.UserID == uid)));
            sumCount = data.Count();
            return data.OrderBy(p => p.PlayTypeID).Skip(skip).Take(take).Select(p => new SchemeDetail_Mod
            {
                DetailID = p.ID,
                Lottery = p.PlayType.LotteryID,
                PlayType = p.PlayType.PlayTypeListID,
                DetailNumber = p.ChoseNumber,
                DetailCount = p.Count,
                DetailMoney = (double)p.Money,
                DetailWinMoney = (double?)p.WinMoney,
                DetailWinNumber = p.WinNumber,
                SchemeOpenCode = p.Scheme.Issue.OpenCode,
                DetailRemark = p.Remark,
                BackMoneyToWinMoney = (double?)p.BackMoneyToWinMoney * 100,
                BackMoneyToWinMoneyToWin = (double?)p.BackMoneyToWinMoneyToWin,
                OriginalWinMoney = (double?)p.OriginalWinMoney,
            });
        }
        #endregion

        /// <summary>
        /// 方案明细 如果ID不为空则忽略其它条件
        /// </summary>
        /// <param name="serch">条件</param>
        /// <param name="loginUid">当前登录的用户</param>
        /// <returns></returns>
        public IEnumerable<SchemeItemModel> GetSchemeDetail(SchemeSerchModel serch, Guid? loginUid)
        {
            var schemes = base.Select(s => s.Select(p => new SchemeItemModel
            {
                SchemeID = p.ID,
                UserName = p.Users.LoginName,
                State = p.State,
                Ratio = p.ConsumptionRatio,
                IsChaseTask = p.IsChaseTask,
                WinMoney = p.WinMoney,
                WinModelID = p.WinModelID,
                AddTime = p.AddTime,
                Commands = p.Users.Commands,
                SchemeCount = p.SchemeCount,
                IssueID = p.IssueID,
                OpenCode = p.Issue.OpenCode,
                IssueName = p.Issue.Number,
                LotteryID = p.LotteryID,
                Multiple = p.Multiple,
                SchemeMoney = p.SchemeMoney,
                UserID = p.UserID,
                Share = p.Share
            }));
            if (loginUid.HasValue)
                schemes = schemes.Where(p => p.Commands.Contains(loginUid.ToString()));
            if (serch == null)
                return schemes;
            if (serch.CommandID.HasValue)
                schemes = schemes.Where(p => p.Commands.Contains(serch.CommandID.ToString()));
            if (serch.ID.HasValue)
            {
                schemes = schemes.Where(p => p.SchemeID == serch.ID);
                return schemes;
            }
            if (!string.IsNullOrEmpty(serch.IssueName))
            {
                if (!serch.LotteryType.HasValue)
                    throw new ValidateException("安期号查找必须指定彩种");
                schemes = schemes.Where(p => p.IssueName == Issue.BulidIssueName(serch.LotteryType.Value, serch.IssueName));
            }
            if (!string.IsNullOrEmpty(serch.UserName))
                schemes = schemes.Where(p => p.UserName == serch.UserName);
            if (serch.StartTime.HasValue)
                schemes = schemes.Where(p => p.AddTime >= serch.StartTime.Value);
            if (serch.EndTime.HasValue)
                schemes = schemes.Where(p => p.AddTime < serch.EndTime.Value.Date.AddDays(1));
            if (serch.WinModel.HasValue)
                schemes = schemes.Where(p => p.WinModelID == serch.WinModel.Value);
            if (serch.Ratio.HasValue)
                schemes = schemes.Where(p => p.Ratio == serch.Ratio.Value);
            if (serch.IsChaseTask.HasValue)
                schemes = schemes.Where(p => p.IsChaseTask == serch.IsChaseTask.Value);
            if (serch.IsWin.HasValue && serch.IsWin.Value)
                schemes = schemes.Where(p => p.State == (short)SchemeState.Opened && p.WinMoney != null);
            else if (serch.IsWin.HasValue && !serch.IsWin.Value)
                schemes = schemes.Where(p => p.State == (short)SchemeState.Opened && p.WinMoney == null);
            else if (serch.State.HasValue)
                schemes = schemes.Where(p => p.State == (short)serch.State.Value);
            if (serch.LotteryType.HasValue)
                schemes = schemes.Where(p => p.LotteryID == (int)serch.LotteryType.Value);

            return schemes;
        }
        public IEnumerable<SchemePlayModel> GetSchemePlays(Guid schemeID)
        {
            IEnumerable<SchemePlayModel> plays = base.Select<Code.Models.Scheme_Detail, IEnumerable<SchemePlayModel>>(s => s
                .Where(p => p.SchemeID == schemeID).Select(p => new SchemePlayModel
                {
                    ID = p.ID,
                    PlayTypeID = p.PlayTypeID,
                    Count = p.Count,
                    Money = p.Money,
                    WinMoney = p.WinMoney,
                    WinNumber = p.WinNumber,
                    Number = p.ChoseNumber,
                    BackMoneyToWinMoney = (double?)p.BackMoneyToWinMoney * 100,
                    BackMoneyToWinMoneyToWin = (double?)p.BackMoneyToWinMoneyToWin,
                    OriginalWinMoney = (double?)p.OriginalWinMoney,
                }));

            return plays;
        }
        public IEnumerable<SchemeWinMoneyModel> GetSchemeWinMoneys(Guid schemeID)
        {
            var wins = base.Select<Models.WinMoneyDetail, IEnumerable<SchemeWinMoneyModel>>(s => s
                .Where(p => p.SchemeID == schemeID).Select(p => new SchemeWinMoneyModel
                {
                    ID = p.ID,
                    AddTime = p.AddTime,
                    Money = p.Money,
                    SchemeID = schemeID,
                    UserID = p.UserID,
                    UserName = p.User.LoginName
                }));
            return wins;
        }

        [Serializable]
        public class SchemeSerchModel
        {
            public Guid? ID { get; set; }
            public DateTime? StartTime { get; set; }
            public DateTime? EndTime { get; set; }
            public LotteryType? LotteryType { get; set; }
            public string IssueName { get; set; }
            public string UserName { get; set; }
            public Guid? CommandID { get; set; }
            public SchemeState? State { get; set; }
            public decimal? Ratio { get; set; }
            public int? WinModel { get; set; }
            public bool? IsChaseTask { get; set; }
            public bool? IsWin { get; set; }
        }
        [Serializable]
        public class SchemeItemModel
        {
            public Guid SchemeID { get; set; }
            public string UserName { get; set; }
            public string Commands { get; set; }
            public Guid UserID { get; set; }
            public DateTime AddTime { get; set; }
            public long IssueID { get; set; }
            public string IssueName { get { var issue = new Issue { LotteryID = LotteryID, Number = _IssueName }; return issue.FormatIssueName; } set { _IssueName = value; } }
            private string _IssueName;
            public int LotteryID { get; set; }
            public string LotteryName { get { return CacheManage.Lottery[(LotteryType)LotteryID].Name; } }
            public short State { get; set; }
            public string StateName { get { return ((SchemeState)State).GetName(); } }
            public string RatioName { get { return CacheManage.Ratio[Ratio].Name; } }
            public decimal Ratio { get; set; }
            public string WinModelName { get { return CacheManage.WinModel[WinModelID].Name; } }
            public int WinModelID { get; set; }
            public bool IsChaseTask { get; set; }
            public int Multiple { get; set; }
            public int Share { get; set; }
            public int SchemeCount { get; set; }
            public decimal SchemeMoney { get; set; }
            public decimal? WinMoney { get; set; }
            public string OpenCode { get; set; }
        }
        [Serializable]
        public class SchemePlayModel
        {
            public Guid ID { get; set; }
            public int PlayTypeID { get; set; }
            public string PlayTypeName { get { return CacheManage.PlayType[PlayTypeID].PlayTypeList.Name; } }
            public int Count { get; set; }
            public decimal Money { get; set; }
            public string Number { get; set; }
            public string WinNumber { get; set; }
            public decimal? WinMoney { get; set; }
            public double? BackMoneyToWinMoney { get; set; }
            public double? BackMoneyToWinMoneyToWin { get; set; }

            public double? OriginalWinMoney { get; set; }
        }
        [Serializable]
        public class SchemeWinMoneyModel
        {
            public long ID { get; set; }
            public Guid UserID { get; set; }
            public string UserName { get; set; }
            public Guid SchemeID { get; set; }
            public DateTime AddTime { get; set; }
            public decimal Money { get; set; }
        }
        [Serializable]
        public class AddDetailItem
        {
            public Guid SchemeID { get; set; }
            public int PlayTypeID { get; set; }
            public short IsCompound { get; set; }
            public string ChoseNumber { get; set; }
            public int Count { get; set; }
            public decimal Money { get; set; }
            public decimal? BackMoneyToWinMoney { get; set; }
        }
    }
}
